﻿package org.leles 
{
	import flash.geom.Point;
	
	/**
	 * 0.0.1 pre alpha
	 * @author Bruno Leles
	 */
	public final class YMath 
	{
		public static const RAD_2_DEGRESS_PROPORTION:Number = 57.295779513082320876798154814105;
		
		public static const DEGRESS_2_RAD_PROPORTION:Number = 0.017453292519943295769236907684886;
		
		/**
		 * Calculate the normal distribution probability of a given X point
		 * @param	x the point with the function will be applied
		 * @param	m (μ) mean
		 * @param	s2 (σ^2) standardDeviation Squared
		 * @return the normal distribution probability of a given x point
		 */
		public static function normalDist(x:Number, m:Number = 0, s2:Number = 1):Number 
		{
			var s:Number		= Math.sqrt( s2 );
			var expoent:Number	= - Math.pow( x - m , 2) / 2 * s2;
			var term:Number		= 1 / ( s * Math.sqrt( 2 * Math.PI ) );
			var y:Number		= term * Math.exp( expoent );
			
			return y;
		}
		
		/**
		 * 
		 * @param	x
		 * @return
		 */
		public function sigmoid(x:Number):Number
		{
			return 1 / ( 1 + Math.exp( -x ) );
		}
		
		/**
		 * returns value if it is beetween min and max, min if value is lower than min and max if its greater
		 * @param	min minimum value
		 * @param	max maximum value
		 * @param	value value ro check
		 * @return a number between min and max value
		 */
		public static function range(min:Number, max:Number, value:Number):Number 
		{
			if ( min > max ) throw new Error("min value greater than max value!");
			return Math.max( min, Math.min( max, value ) );
		}
		
		/**
		 * returns a random value between min and max value
		 * @param	min
		 * @param	max
		 * @param	roundResult
		 * @return
		 */
		public static function randomRange(min:Number, max:Number, roundResult:Boolean = false): Number
		{
			var result:Number = min + Math.random() * ( max - min );
			if ( roundResult ) result = Math.round( result );
			return result;
		}
		
		/**
		 * converts a rad value to dregrees
		 * @param	radValue
		 * @param	useFastConversion
		 * @return
		 */
		public static function rad2degress(radValue:Number, useFastConversion:Boolean = true):Number
		{
			var conversor:Number = useFastConversion ? RAD_2_DEGRESS_PROPORTION : 180 / Math.PI;
			return radValue * conversor;
		}
		
		/**
		 * converts a dregrees value to rad
		 * @param	radValue
		 * @param	useFastConversion
		 * @return
		 */
		public static function degrees2rad(degValue:Number, useFastConversion:Boolean = true):Number
		{
			var conversor:Number = useFastConversion ? DEGRESS_2_RAD_PROPORTION : Math.PI / 180;
			return degValue * conversor
		}
		
		/**
		 * casteljau
		 * @param	points
		 * @param	t
		 * @return
		 */
		public static function casteljau(points:Array/*of Point*/, t:Number):Point
		{
			var p:Array = [];
			var i:int,
				j:int, 
				j1:int,
				n:int = points.length,
				nj:int,
				ti:Number = 1 - t;
				
			for (i = 0; i < n; i++)
			{
				p.push(points[i].clone());
			}
			for (i = 1; i < n; i++)
			{
				nj = n - i;
				for (j = 0; j < nj; j++)
				{
					j1 = j + 1;
					p[j].x = (ti) * p[j].x + t * p[j + j1].x;
					p[j].y = (ti) * p[j].y + t * p[j + j1].y;
				}
			}
			return p[0];
		}
	}
}